using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Xml.Linq;
using DeclarativeTest.Core.Support;

namespace DeclarativeTest.Core
{
	public class TestSuiteInfo : IDataProvider
	{
		#region Fields

		private readonly NameValueCollection _arguments = new NameValueCollection( StringComparer.InvariantCultureIgnoreCase );
		private readonly List<ImportInfo> _imports = new List<ImportInfo>();

		private readonly IDictionary<string,object> _properties = new Dictionary<string,object>( StringComparer.InvariantCultureIgnoreCase );

		private readonly List<ActionInfo> _beforeAll = new List<ActionInfo>();
		private readonly List<ActionInfo> _afterAll = new List<ActionInfo>();
		private readonly List<ActionInfo> _beforeEach = new List<ActionInfo>();
		private readonly List<ActionInfo> _afterEach = new List<ActionInfo>();

		private readonly List<TestCaseInfo> _tests = new List<TestCaseInfo>();

		#endregion

		#region Properties

		/// <summary>
		/// Test suite name
		/// </summary>
		public string Name{ get; set; }
	
		/// <summary>
		/// TestSuite Arguments
		/// </summary>
		public NameValueCollection Arguments
		{
			get { return _arguments; }
		}

		/// <summary>
		/// Imports
		/// </summary>
		public ICollection<ImportInfo> Imports
		{
			get { return _imports; }
		}

		/// <summary>
		/// TestSuite common properties
		/// </summary>
		public IDictionary<string,object> Properties
		{
			get { return _properties; }
		}

		/// <summary>
		/// Test list
		/// </summary>
		public ICollection<TestCaseInfo> Tests
		{
			get { return _tests; }
		}

		#endregion

		public ICollection<ActionInfo> BeforeAll
		{
			get { return _beforeAll; }
		}

		public ICollection<ActionInfo> AfterAll
		{
			get { return _afterAll; }
		}

		public ICollection<ActionInfo> BeforeEach
		{
			get { return _beforeEach; }
		}

		public ICollection<ActionInfo> AfterEach
		{
			get { return _afterEach; }
		}

		#region Methods

		/// <summary>
		/// Adds import
		/// </summary>
		/// <param name="importInfo">ImportInfo</param>
		public void AddImport( ImportInfo importInfo )
		{
			_imports.Add( importInfo );
		}

		/// <summary>
		/// Adds test
		/// </summary>
		/// <param name="test">TestCaseInfo</param>
		public void AddTest( TestCaseInfo test )
		{
			_tests.Add( test );
		}

		#endregion

		public override string ToString( )
		{
			return string.Format( "TestSuite: {0}", Name );
		}

	}

	public class ImportInfo
	{
		public string Assembly{ get; set; }
	}

	public class TestCaseInfo : IHierarchicalDataProvider
	{
		#region Fields

		private IDataProvider _parent;

		private readonly Dictionary<string,string> _arguments = new Dictionary<string,string>( StringComparer.InvariantCultureIgnoreCase );
		private readonly List<ActionInfo> _actions = new List<ActionInfo>();
		private readonly IDictionary<string,object> _properties = new Dictionary<string,object>( StringComparer.InvariantCultureIgnoreCase );

		#endregion

		/// <summary>
		/// Initializes a new instance of the <see cref="T:System.Object"/> class.
		/// </summary>
		public TestCaseInfo( IDataProvider parent )
		{
			_parent = parent;
		}

		#region Properties

		public string Name{ get; set; }

        public string Description
	    {
	        get{ return GetTestCaseAttribute(TestCaseAttribute.Description); }
	    }

        public string Category
	    {
	        get{ return GetTestCaseAttribute(TestCaseAttribute.Category); }
	    }

		public string GetTestCaseAttribute( TestCaseAttribute testCaseAttribute )
		{
			return _arguments.GetValue(testCaseAttribute.ToString(),null);
		}

		public Dictionary<string,string> Arguments
		{
			get { return _arguments; }
		}

		public ICollection<ActionInfo> Actions
		{
			get { return _actions; }
		}

		public bool Ignore
		{
			get
			{
				return Arguments.GetValue( TestCaseAttribute.Ignore.ToString(), false );
			}
		}

        public string IgnoreReason
	    {
	        get{ return GetTestCaseAttribute(TestCaseAttribute.IgnoreReason); }
	    }

		#endregion

		public override string ToString( )
		{
			return "TestCase: {0}".WithArgs( Name );
		}

		#region Implementation of IDataProvider

		/// <summary>
		/// Properties.
		/// </summary>
		public IDictionary<string,object> Properties
		{
			get { return _properties; }
		}

		#endregion

		#region Implementation of IHierarchicalDataProvider

		/// <summary>
		/// Parent <see cref="IDataProvider"/>
		/// </summary>
		public IDataProvider ParentDataProvider
		{
			get { return _parent; }
		}

		#endregion
	}

	public class ActionInfo
	{
		private readonly IDictionary _arguments = new Hashtable( StringComparer.InvariantCultureIgnoreCase );

		public XName Name{ get; set; }

		public IDictionary Arguments
		{
			get { return _arguments; }
		}

		public override string ToString( )
		{
			StringBuilder sb = new StringBuilder();
			sb.AppendFormat( "Action: {0}( ", Name );
			foreach ( DictionaryEntry entry in Arguments )
			{
				sb.AppendFormat("{0}='{1}', ",  entry.Key, entry.Value );
			}
			sb.Length -= 1;
			sb.Append( " )" );
			return sb.ToString();
		}
	}

	public enum TestSuiteAttributes
	{
		Culture,
		FileName
	}
	public enum TestCaseAttribute
	{
		Description,
		Category,
		Ignore,
		IgnoreReason
	}
}